package com.github.aloxc.plugin.restplus.swagger;

import com.github.aloxc.plugin.restplus.common.PsiClassHelper;
import com.github.aloxc.plugin.restplus.entity.EnvironmentConfig;
import com.github.aloxc.plugin.restplus.entity.SwaggerConfig;
import com.github.aloxc.plugin.restplus.entity.SwaggerRequest;
import com.github.aloxc.plugin.restplus.method.HttpMethod;
import com.github.aloxc.plugin.restplus.utils.JsonUtils;
import com.github.aloxc.plugin.restplus.utils.StringUtils;
import com.intellij.openapi.project.Project;

import java.util.*;

public class Swagger2 implements SwaggerAdapter {
    private Project project;

    public Swagger2(Project project) {
        this.project = project;
    }



    @Override
    public SwaggerConfig getApiInfo(HashMap json) {
        HashMap paths = (HashMap) json.get("paths");
        HashMap info = (HashMap)json.get("info");
        String title = (String) info.get("title");
        HashMap definitions = (HashMap) json.get("definitions");
        Map<String,List<SwaggerParameterSwap>> paramMap = new HashMap(16);
        for (String name : (Set<String>)definitions.keySet()){
            HashMap properties = (HashMap) ((HashMap)definitions.get(name)).get("properties");
            if(properties == null){
                continue;
            }
            List<SwaggerParameterSwap> parameterSwapList = new ArrayList<>();
            for(String paramName : (Set<String>)properties.keySet()){
                SwaggerParameterSwap swaggerParameterSwap = new SwaggerParameterSwap();
                parameterSwapList.add(swaggerParameterSwap);
                HashMap paramDescription = (HashMap) properties.get(paramName);
                Object type = paramDescription.get("type");
                String description = (String) paramDescription.get("description");
                swaggerParameterSwap.setDescription(description);
                swaggerParameterSwap.setName(paramName);
                if(type == null){
                    //是引用别的类
                    String typeRef = (String) paramDescription.get("originalRef");
                    swaggerParameterSwap.setValue(typeRef);
                    swaggerParameterSwap.setParamType(SwaggerParameterType.OBJECT);
                }else{
                    if("array".equals(type)){
                        //数组或者list
                        HashMap items = (HashMap) paramDescription.get("items");
                        if(items.containsKey("originalRef")){
                            //list或者数组引用别的类
                            swaggerParameterSwap.setParamType(SwaggerParameterType.ARRAY_OBJECT);
                            swaggerParameterSwap.setValue(items.get("originalRef"));
                        }else{
                            //简单类型或者还是数组。。。TODO
                            swaggerParameterSwap.setParamType(SwaggerParameterType.ARRAY);
                            Object type1 = items.get("type");
                            List values = new ArrayList();
                            if("array".equals(type1)){
                                //是数组(不管是什么数组)的不处理了，
                                swaggerParameterSwap.setValue(values);
                            }else{
                                Object value = PsiClassHelper.getJavaBaseTypeDefaultValue((String) type1);
                                values.add(value);
                                swaggerParameterSwap.setValue(values);
                            }
                        }
                    }else{
                        //基本类型
                        swaggerParameterSwap.setParamType(SwaggerParameterType.SIMPLE);
                        Object value = PsiClassHelper.getJavaBaseTypeDefaultValue((String) type);
                        swaggerParameterSwap.setValue(value);
                    }
                }
            }
            paramMap.put(name,parameterSwapList);
        }
        //解决对象中引用的问题
        for(String clazz : paramMap.keySet()){
            List<SwaggerParameterSwap> parameterSwapList = paramMap.get(clazz);
            for(SwaggerParameterSwap swap : parameterSwapList){
                SwaggerParameterType paramType = swap.getParamType();
                if(paramType == SwaggerParameterType.OBJECT){
                    swap.setValue(paramMap.get(swap.getValue()));
                }else if(paramType == SwaggerParameterType.ARRAY_OBJECT){
                    List list = new ArrayList();
                    list.add(paramMap.get(swap.getValue()));
                    swap.setValue(list);
                }
            }
        }
        //把临时的对象转换成swagger参数
        Map<String,List<SwaggerParameter>> swaggerParameterMap = new HashMap<>(16);
        for(String clazz : paramMap.keySet()){
            List<SwaggerParameter> parameterList = new ArrayList<>();
            List<SwaggerParameterSwap> parameterSwapList = paramMap.get(clazz);
            for(SwaggerParameterSwap swap : parameterSwapList){
                SwaggerParameterType paramType = swap.getParamType();
                SwaggerParameter swaggerParameter = new SwaggerParameter();
                parameterList.add(swaggerParameter);
                swaggerParameter.setName(swap.getName());
                swaggerParameter.setDescription(swap.getDescription());
                if(swap.getParamType() == SwaggerParameterType.ARRAY_OBJECT || swap.getParamType() == SwaggerParameterType.OBJECT) {
                    swaggerParameter.setValue(paramMap.get(swap.getValue()));
                }else {
                    swaggerParameter.setValue(swap.getValue());
                }
            }
            swaggerParameterMap.put(clazz,parameterList);
        }
        SwaggerConfig swaggerConfig = new SwaggerConfig();
        List<SwaggerRequest> swaggerRequestList = new ArrayList<>();
        swaggerConfig.setName(title);
        swaggerConfig.setSwaggerRequestList(swaggerRequestList);
        for(String url : (Set<String>)paths.keySet()){
            if("$ref".equals(url)){
                continue;
            }
            HashMap methMap = (HashMap) paths.get(url);
            for(String meth : (Set<String>)methMap.keySet()) {
                HttpMethod method = HttpMethod.getByRequestMethod(meth);
                HashMap api = (HashMap) methMap.get(meth);
                String summary = (String) api.get("summary");
                Object parameters = api.get("parameters");
                List<SwaggerParameter> swaggerParameterList = new ArrayList<>();
                if(parameters != null){
                    List<HashMap> paramList = (List<HashMap>) parameters;
                    String paramx = null;
                    for(HashMap param : paramList){
                        if("body".equals(param.get("in"))){
                            //只要是有body就不用管其它参数了
                            method = HttpMethod.POST_BODY;
                            if(param.containsKey("schema")){
                                HashMap schema = (HashMap) param.get("schema");
                                if(schema.containsKey("originalRef")){
                                    swaggerParameterList = swaggerParameterMap.get(schema.get("originalRef"));
//                                    System.out.println(schema.get("originalRef") + "\t" + JsonUtils.toJson(swaggerParameterMap.get(schema.get("originalRef")),false));
                                }
                            }
                            break;
                        }else{
                            SwaggerParameter swaggerParameter = new SwaggerParameter();
                            swaggerParameter.setName((String) param.get("name"));
                            swaggerParameter.setValue(PsiClassHelper.getJavaBaseTypeDefaultValue((String) param.get("type")));
                            swaggerParameter.setDescription((String) param.get("description"));
                            swaggerParameterList.add(swaggerParameter);
                        }
                    }
                }
                SwaggerRequest swaggerRequest = new SwaggerRequest();
                swaggerRequest.setDescription(summary);
                swaggerRequest.setMethod(method);
                swaggerRequest.setName(summary);
                swaggerRequest.setUrl(url);
                swaggerRequest.setParam(JsonUtils.toJson(swaggerParameterList,false));
                swaggerRequestList.add(swaggerRequest);
            }
        }
        return swaggerConfig;
    }

    @Override
    public EnvironmentConfig getEnvironmentConfig(HashMap json) {
        EnvironmentConfig config = new EnvironmentConfig();
        HashMap info = (HashMap)json.get("info");
        String title = (String) info.get("title");
        String host = (String) json.get("host");
        int port = 80;
        if(StringUtils.isNullOrEmpty(host)){
            host = "localhost";
        }else{
            boolean contains = host.contains(":");
            if(contains){
                String[] split = host.split(":");
                host = split[0];
                port = Integer.parseInt(split[1]);
            }
        }
        String basePath = (String)json.get("basePath");
        if(StringUtils.isNullOrEmpty(basePath) || "/".equals(basePath)){
            basePath = "";
        }
        config.setSelected(false);
        config.setHost(host);
        config.setPort(port);
        config.setHttps(false);
        config.setTest("");
        config.setContext(basePath);
        config.setName(title);
        config.setSettingList(new Vector<>());
        return config;
    }

}
